package com.example.demo.utils;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.demo.constans.CacheConstants;
import com.example.demo.excepiton.CustomException;
import com.example.demo.pojo.bo.LoginUserBo;
import com.example.demo.pojo.entity.UserEntity;
import com.example.demo.service.IUserService;
import com.example.demo.service.UserServiceImpl;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限获取工具类
 *
 * @author hecheng
 */

public class SecurityUtils {
    public static final String key = "xxxxxx";


    /**
     * 获取用户
     */
    public static LoginUserBo getUserInfo() {

        HttpServletRequest request = ServletUtils.getRequest();

        String token = request.getHeader(CacheConstants.HEADER);

        Long expireTimeByToken = getExpireTimeByToken(token);
        if (expireTimeByToken == null){
            throw new CustomException("getUserInfo：登录状态已过期.");
        }
        Long userIdByToken = SecurityUtils.getUserIdByToken(token);
        RedisService redisService = SpringUtils.getBean(RedisService.class);
        String userStr = redisService.getValue(CacheConstants.LOGIN_TOKEN_KEY + userIdByToken);
        if (!org.springframework.util.StringUtils.isEmpty(userStr)){
            LoginUserBo loginUser = JSON.parseObject(userStr, LoginUserBo.class);
            if (null == loginUser
                    || StringUtils.isBlank(loginUser.getUserEntity().getUserName())
                    || null == loginUser.getUserEntity().getUserId()) {
                throw new CustomException("该用户未授权登录,获取用户信息失败.",501);
            }
            return loginUser;
        }
        UserEntity byId = SpringUtils.getBean(IUserService.class).getById(expireTimeByToken);
        if (!ObjectUtils.isEmpty(byId)){
            LoginUserBo loginBO = SpringUtils.getBean(UserServiceImpl.class).getLoginBO(byId);
            redisService.cacheValue(CacheConstants.LOGIN_TOKEN_KEY+byId.getUserId(), JSON.toJSONString(loginBO),60*10L);
            return loginBO;
        }else {
            throw new CustomException("非法用户",501);
        }

    }


    /*  *//**
     * 获取用户项目
     *
     * @return 项目结果集
     *//*
    public static List<String> getProjects()
    {
        LoginUserBO loginUser = getUserInfo();
        if(StringUtils.isBlank(loginUser.getProjects())
                && !loginUser.getSysUser().getUserType().equals(Constants.USER_ADMIN)){
            throw new BaseException("未分配项目,请联系系统管理员");
        }else if (StringUtils.isBlank(loginUser.getProjects())
                && !loginUser.getSysUser().getUserType().equals(Constants.USER_ONE)
                && !loginUser.getSysUser().getUserType().equals(Constants.USER_ADMIN)){
            throw new BaseException("未分配项目,请联系公司管理员");
        }
        List<String> result = Arrays.asList(loginUser.getProjects().split(","));
        return  result;
    }*/


    /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param password 密码
     * @return 加密字符串
     */
    public static String encryptPassword(String password) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.encode(password);
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword     真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }
    /**
     *  通过token得到用户id
     * @author mhx
     * @date 2022/5/18 4:22 下午
     * @param token
     * @return java.lang.Long
     */
    public static Long getUserIdByToken(String token) {
        try {
            Claims body = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
            String id = body.getId();

            return Long.parseLong(id);
        } catch (Exception e) {
            return null;

        }

    }
    public static Long getUserIdByToken() {
        String token = ServletUtils.getToken();
        try {
            Claims body = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
            String id = body.getId();

            return Long.parseLong(id);
        } catch (Exception e) {
            return null;

        }

    }
    /**
     *  通过token得到过期时间， 如果为null就是已过期
     * @author mhx
     * @date 2022/5/18 4:23 下午
     * @param token
     * @return java.lang.Long
     */
    public static Long getExpireTimeByToken(String token) {
        try {
            Claims body = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
            Date expiration = body.getExpiration();

            return expiration.getTime();
        } catch (Exception e) {
            return null;

        }
    }
    public static String createJWT(String id) {
        long now = System.currentTimeMillis();//当前时间
        long exp = now + 60*60*1000*24*7L;//过期时间为60分钟
        JwtBuilder builder = Jwts.builder().setId(id)
//                难道不是直接放到subject吗？
//                .setClaims(map)为啥要单个处理claim//为啥要批量处理claim
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, key)//签名的时候，JwtBuilder把这个key做了一次base64
                .setExpiration(new Date(exp));//用于设置过期时间;
        return builder.compact();
    }

}
